package approachingjvm.classloader;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ClassLoaderTest {
    public static void main(String[] args) throws ClassNotFoundException {
        ClassLoader selfClassLoader = ClassLoaderTest.class.getClassLoader();
        ClassLoader threadClassLoader = Thread.currentThread().getContextClassLoader();
        System.out.println("selfClassLoader == threadClassLoader is " + (selfClassLoader == threadClassLoader));

        System.out.println("String.class.getClassLoader() = " + String.class.getClassLoader());
        System.out.println("int[].class.getClassLoader() = " + int[].class.getClassLoader());

        dumpClassLoaderParents(selfClassLoader);
        dumpClassLoaderParents(threadClassLoader);

        Class<?> class1 = selfClassLoader.loadClass("approachingjvm.classloader.MyClass1");
        System.out.println("first time load");
        Class<?> class2 = selfClassLoader.loadClass("approachingjvm.classloader.MyClass1");
        System.out.println("second time load");

        System.out.println("class1 == class2 is " + (class1 == class2));

        Class clazz;
        UselessClassLoader uselessClassLoader = new UselessClassLoader(selfClassLoader);
        clazz = uselessClassLoader.loadClass("approachingjvm.classloader.MyClass1");
        clazz = uselessClassLoader.loadClass("approachingjvm.classloader.MyClass2");
        try {
            Method findClassProtectedMethod = ClassLoader.class.getDeclaredMethod("findClass", String.class);
            findClassProtectedMethod.setAccessible(true);
            clazz = (Class) findClassProtectedMethod.invoke(selfClassLoader, "approachingjvm.classloader.MyClass3");
            clazz = (Class) findClassProtectedMethod.invoke(selfClassLoader, "approachingjvm.classloader.MyClass3");
            System.out.println("ok");
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        // 小trick
        clazz = uselessClassLoader.findClass("approachingjvm.classloader.MyClass1");

        System.out.println("end");
    }

    private static void dumpClassLoaderParents(ClassLoader classLoader) {
        while (classLoader != null) {
            System.out.println(classLoader);
            classLoader = classLoader.getParent();
        }
        System.out.println("end");
    }
}
